home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / httplib.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2008-10-13  |  29.4 KB  |  1,208 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. import errno
  5. import mimetools
  6. import socket
  7. from urlparse import urlsplit
  8.  
  9. try:
  10.     from cStringIO import StringIO
  11. except ImportError:
  12.     from StringIO import StringIO
  13.  
  14. __all__ = [
  15.     'HTTP',
  16.     'HTTPResponse',
  17.     'HTTPConnection',
  18.     'HTTPSConnection',
  19.     'HTTPException',
  20.     'NotConnected',
  21.     'UnknownProtocol',
  22.     'UnknownTransferEncoding',
  23.     'UnimplementedFileMode',
  24.     'IncompleteRead',
  25.     'InvalidURL',
  26.     'ImproperConnectionState',
  27.     'CannotSendRequest',
  28.     'CannotSendHeader',
  29.     'ResponseNotReady',
  30.     'BadStatusLine',
  31.     'error',
  32.     'responses']
  33. HTTP_PORT = 80
  34. HTTPS_PORT = 443
  35. _UNKNOWN = 'UNKNOWN'
  36. _CS_IDLE = 'Idle'
  37. _CS_REQ_STARTED = 'Request-started'
  38. _CS_REQ_SENT = 'Request-sent'
  39. CONTINUE = 100
  40. SWITCHING_PROTOCOLS = 101
  41. PROCESSING = 102
  42. OK = 200
  43. CREATED = 201
  44. ACCEPTED = 202
  45. NON_AUTHORITATIVE_INFORMATION = 203
  46. NO_CONTENT = 204
  47. RESET_CONTENT = 205
  48. PARTIAL_CONTENT = 206
  49. MULTI_STATUS = 207
  50. IM_USED = 226
  51. MULTIPLE_CHOICES = 300
  52. MOVED_PERMANENTLY = 301
  53. FOUND = 302
  54. SEE_OTHER = 303
  55. NOT_MODIFIED = 304
  56. USE_PROXY = 305
  57. TEMPORARY_REDIRECT = 307
  58. BAD_REQUEST = 400
  59. UNAUTHORIZED = 401
  60. PAYMENT_REQUIRED = 402
  61. FORBIDDEN = 403
  62. NOT_FOUND = 404
  63. METHOD_NOT_ALLOWED = 405
  64. NOT_ACCEPTABLE = 406
  65. PROXY_AUTHENTICATION_REQUIRED = 407
  66. REQUEST_TIMEOUT = 408
  67. CONFLICT = 409
  68. GONE = 410
  69. LENGTH_REQUIRED = 411
  70. PRECONDITION_FAILED = 412
  71. REQUEST_ENTITY_TOO_LARGE = 413
  72. REQUEST_URI_TOO_LONG = 414
  73. UNSUPPORTED_MEDIA_TYPE = 415
  74. REQUESTED_RANGE_NOT_SATISFIABLE = 416
  75. EXPECTATION_FAILED = 417
  76. UNPROCESSABLE_ENTITY = 422
  77. LOCKED = 423
  78. FAILED_DEPENDENCY = 424
  79. UPGRADE_REQUIRED = 426
  80. INTERNAL_SERVER_ERROR = 500
  81. NOT_IMPLEMENTED = 501
  82. BAD_GATEWAY = 502
  83. SERVICE_UNAVAILABLE = 503
  84. GATEWAY_TIMEOUT = 504
  85. HTTP_VERSION_NOT_SUPPORTED = 505
  86. INSUFFICIENT_STORAGE = 507
  87. NOT_EXTENDED = 510
  88. responses = {
  89.     100: 'Continue',
  90.     101: 'Switching Protocols',
  91.     200: 'OK',
  92.     201: 'Created',
  93.     202: 'Accepted',
  94.     203: 'Non-Authoritative Information',
  95.     204: 'No Content',
  96.     205: 'Reset Content',
  97.     206: 'Partial Content',
  98.     300: 'Multiple Choices',
  99.     301: 'Moved Permanently',
  100.     302: 'Found',
  101.     303: 'See Other',
  102.     304: 'Not Modified',
  103.     305: 'Use Proxy',
  104.     306: '(Unused)',
  105.     307: 'Temporary Redirect',
  106.     400: 'Bad Request',
  107.     401: 'Unauthorized',
  108.     402: 'Payment Required',
  109.     403: 'Forbidden',
  110.     404: 'Not Found',
  111.     405: 'Method Not Allowed',
  112.     406: 'Not Acceptable',
  113.     407: 'Proxy Authentication Required',
  114.     408: 'Request Timeout',
  115.     409: 'Conflict',
  116.     410: 'Gone',
  117.     411: 'Length Required',
  118.     412: 'Precondition Failed',
  119.     413: 'Request Entity Too Large',
  120.     414: 'Request-URI Too Long',
  121.     415: 'Unsupported Media Type',
  122.     416: 'Requested Range Not Satisfiable',
  123.     417: 'Expectation Failed',
  124.     500: 'Internal Server Error',
  125.     501: 'Not Implemented',
  126.     502: 'Bad Gateway',
  127.     503: 'Service Unavailable',
  128.     504: 'Gateway Timeout',
  129.     505: 'HTTP Version Not Supported' }
  130. MAXAMOUNT = 1048576
  131.  
  132. class HTTPMessage(mimetools.Message):
  133.     
  134.     def addheader(self, key, value):
  135.         prev = self.dict.get(key)
  136.         if prev is None:
  137.             self.dict[key] = value
  138.         else:
  139.             combined = ', '.join((prev, value))
  140.             self.dict[key] = combined
  141.  
  142.     
  143.     def addcontinue(self, key, more):
  144.         prev = self.dict[key]
  145.         self.dict[key] = prev + '\n ' + more
  146.  
  147.     
  148.     def readheaders(self):
  149.         self.dict = { }
  150.         self.unixfrom = ''
  151.         self.headers = hlist = []
  152.         self.status = ''
  153.         headerseen = ''
  154.         firstline = 1
  155.         startofline = None
  156.         unread = None
  157.         tell = None
  158.         if hasattr(self.fp, 'unread'):
  159.             unread = self.fp.unread
  160.         elif self.seekable:
  161.             tell = self.fp.tell
  162.         
  163.         while True:
  164.             if tell:
  165.                 
  166.                 try:
  167.                     startofline = tell()
  168.                 except IOError:
  169.                     startofline = None
  170.                     tell = None
  171.                     self.seekable = 0
  172.                 except:
  173.                     None<EXCEPTION MATCH>IOError
  174.                 
  175.  
  176.             None<EXCEPTION MATCH>IOError
  177.             line = self.fp.readline()
  178.             if not line:
  179.                 self.status = 'EOF in headers'
  180.                 break
  181.             
  182.             if firstline and line.startswith('From '):
  183.                 self.unixfrom = self.unixfrom + line
  184.                 continue
  185.             
  186.             firstline = 0
  187.             if headerseen and line[0] in ' \t':
  188.                 hlist.append(line)
  189.                 self.addcontinue(headerseen, line.strip())
  190.                 continue
  191.             elif self.iscomment(line):
  192.                 continue
  193.             elif self.islast(line):
  194.                 break
  195.             
  196.             headerseen = self.isheader(line)
  197.             if headerseen:
  198.                 hlist.append(line)
  199.                 self.addheader(headerseen, line[len(headerseen) + 1:].strip())
  200.                 continue
  201.                 continue
  202.             if not self.dict:
  203.                 self.status = 'No headers'
  204.             else:
  205.                 self.status = 'Non-header line where header expected'
  206.             if unread:
  207.                 unread(line)
  208.             elif tell:
  209.                 self.fp.seek(startofline)
  210.             else:
  211.                 self.status = self.status + '; bad seek'
  212.             break
  213.  
  214.  
  215.  
  216. class HTTPResponse:
  217.     
  218.     def __init__(self, sock, debuglevel = 0, strict = 0, method = None):
  219.         self.fp = sock.makefile('rb', 0)
  220.         self.debuglevel = debuglevel
  221.         self.strict = strict
  222.         self._method = method
  223.         self.msg = None
  224.         self.version = _UNKNOWN
  225.         self.status = _UNKNOWN
  226.         self.reason = _UNKNOWN
  227.         self.chunked = _UNKNOWN
  228.         self.chunk_left = _UNKNOWN
  229.         self.length = _UNKNOWN
  230.         self.will_close = _UNKNOWN
  231.  
  232.     
  233.     def _read_status(self):
  234.         line = self.fp.readline()
  235.         if self.debuglevel > 0:
  236.             print 'reply:', repr(line)
  237.         
  238.         if not line:
  239.             raise BadStatusLine(line)
  240.         
  241.         
  242.         try:
  243.             (version, status, reason) = line.split(None, 2)
  244.         except ValueError:
  245.             
  246.             try:
  247.                 (version, status) = line.split(None, 1)
  248.                 reason = ''
  249.             except ValueError:
  250.                 version = ''
  251.             except:
  252.                 None<EXCEPTION MATCH>ValueError
  253.             
  254.  
  255.             None<EXCEPTION MATCH>ValueError
  256.  
  257.         if not version.startswith('HTTP/'):
  258.             if self.strict:
  259.                 self.close()
  260.                 raise BadStatusLine(line)
  261.             else:
  262.                 self.fp = LineAndFileWrapper(line, self.fp)
  263.                 return ('HTTP/0.9', 200, '')
  264.         
  265.         
  266.         try:
  267.             status = int(status)
  268.             if status < 100 or status > 999:
  269.                 raise BadStatusLine(line)
  270.         except ValueError:
  271.             raise BadStatusLine(line)
  272.  
  273.         return (version, status, reason)
  274.  
  275.     
  276.     def begin(self):
  277.         if self.msg is not None:
  278.             return None
  279.         
  280.         while True:
  281.             (version, status, reason) = self._read_status()
  282.             if status != CONTINUE:
  283.                 break
  284.             
  285.             while True:
  286.                 skip = self.fp.readline().strip()
  287.                 if not skip:
  288.                     break
  289.                 
  290.                 if self.debuglevel > 0:
  291.                     print 'header:', skip
  292.                     continue
  293.         self.status = status
  294.         self.reason = reason.strip()
  295.         if version == 'HTTP/1.0':
  296.             self.version = 10
  297.         elif version.startswith('HTTP/1.'):
  298.             self.version = 11
  299.         elif version == 'HTTP/0.9':
  300.             self.version = 9
  301.         else:
  302.             raise UnknownProtocol(version)
  303.         if self.version == 9:
  304.             self.length = None
  305.             self.chunked = 0
  306.             self.will_close = 1
  307.             self.msg = HTTPMessage(StringIO())
  308.             return None
  309.         
  310.         self.msg = HTTPMessage(self.fp, 0)
  311.         if self.debuglevel > 0:
  312.             for hdr in self.msg.headers:
  313.                 print 'header:', hdr,
  314.             
  315.         
  316.         self.msg.fp = None
  317.         tr_enc = self.msg.getheader('transfer-encoding')
  318.         if tr_enc and tr_enc.lower() == 'chunked':
  319.             self.chunked = 1
  320.             self.chunk_left = None
  321.         else:
  322.             self.chunked = 0
  323.         self.will_close = self._check_close()
  324.         length = self.msg.getheader('content-length')
  325.         if length and not (self.chunked):
  326.             
  327.             try:
  328.                 self.length = int(length)
  329.             except ValueError:
  330.                 self.length = None
  331.             except:
  332.                 None<EXCEPTION MATCH>ValueError
  333.             
  334.  
  335.         None<EXCEPTION MATCH>ValueError
  336.         self.length = None
  337.         if not status == NO_CONTENT and status == NOT_MODIFIED:
  338.             if status <= status:
  339.                 pass
  340.             elif status < 200 or self._method == 'HEAD':
  341.                 self.length = 0
  342.             
  343.         if not (self.will_close) and not (self.chunked) and self.length is None:
  344.             self.will_close = 1
  345.         
  346.  
  347.     
  348.     def _check_close(self):
  349.         conn = self.msg.getheader('connection')
  350.         if self.version == 11:
  351.             conn = self.msg.getheader('connection')
  352.             if conn and 'close' in conn.lower():
  353.                 return True
  354.             
  355.             return False
  356.         
  357.         if self.msg.getheader('keep-alive'):
  358.             return False
  359.         
  360.         if conn and 'keep-alive' in conn.lower():
  361.             return False
  362.         
  363.         pconn = self.msg.getheader('proxy-connection')
  364.         if pconn and 'keep-alive' in pconn.lower():
  365.             return False
  366.         
  367.         return True
  368.  
  369.     
  370.     def close(self):
  371.         if self.fp:
  372.             self.fp.close()
  373.             self.fp = None
  374.         
  375.  
  376.     
  377.     def isclosed(self):
  378.         return self.fp is None
  379.  
  380.     
  381.     def read(self, amt = None):
  382.         if self.fp is None:
  383.             return ''
  384.         
  385.         if self.chunked:
  386.             return self._read_chunked(amt)
  387.         
  388.         if amt is None:
  389.             if self.length is None:
  390.                 s = self.fp.read()
  391.             else:
  392.                 s = self._safe_read(self.length)
  393.                 self.length = 0
  394.             self.close()
  395.             return s
  396.         
  397.         if self.length is not None:
  398.             if amt > self.length:
  399.                 amt = self.length
  400.             
  401.         
  402.         s = self.fp.read(amt)
  403.         if self.length is not None:
  404.             self.length -= len(s)
  405.         
  406.         return s
  407.  
  408.     
  409.     def _read_chunked(self, amt):
  410.         chunk_left = self.chunk_left
  411.         value = ''
  412.         while True:
  413.             if chunk_left is None:
  414.                 line = self.fp.readline()
  415.                 i = line.find(';')
  416.                 if i >= 0:
  417.                     line = line[:i]
  418.                 
  419.                 chunk_left = int(line, 16)
  420.                 if chunk_left == 0:
  421.                     break
  422.                 
  423.             
  424.             if amt is None:
  425.                 value += self._safe_read(chunk_left)
  426.             elif amt < chunk_left:
  427.                 value += self._safe_read(amt)
  428.                 self.chunk_left = chunk_left - amt
  429.                 return value
  430.             elif amt == chunk_left:
  431.                 value += self._safe_read(amt)
  432.                 self._safe_read(2)
  433.                 self.chunk_left = None
  434.                 return value
  435.             else:
  436.                 value += self._safe_read(chunk_left)
  437.                 amt -= chunk_left
  438.             self._safe_read(2)
  439.             chunk_left = None
  440.         while True:
  441.             line = self.fp.readline()
  442.             if not line:
  443.                 break
  444.             
  445.             if line == '\r\n':
  446.                 break
  447.                 continue
  448.         self.close()
  449.         return value
  450.  
  451.     
  452.     def _safe_read(self, amt):
  453.         s = []
  454.         while amt > 0:
  455.             chunk = self.fp.read(min(amt, MAXAMOUNT))
  456.             if not chunk:
  457.                 raise IncompleteRead(s)
  458.             
  459.             s.append(chunk)
  460.             amt -= len(chunk)
  461.         return ''.join(s)
  462.  
  463.     
  464.     def getheader(self, name, default = None):
  465.         if self.msg is None:
  466.             raise ResponseNotReady()
  467.         
  468.         return self.msg.getheader(name, default)
  469.  
  470.     
  471.     def getheaders(self):
  472.         if self.msg is None:
  473.             raise ResponseNotReady()
  474.         
  475.         return self.msg.items()
  476.  
  477.  
  478.  
  479. class HTTPConnection:
  480.     _http_vsn = 11
  481.     _http_vsn_str = 'HTTP/1.1'
  482.     response_class = HTTPResponse
  483.     default_port = HTTP_PORT
  484.     auto_open = 1
  485.     debuglevel = 0
  486.     strict = 0
  487.     
  488.     def __init__(self, host, port = None, strict = None):
  489.         self.sock = None
  490.         self._buffer = []
  491.         self._HTTPConnection__response = None
  492.         self._HTTPConnection__state = _CS_IDLE
  493.         self._method = None
  494.         self._set_hostport(host, port)
  495.         if strict is not None:
  496.             self.strict = strict
  497.         
  498.  
  499.     
  500.     def _set_hostport(self, host, port):
  501.         if port is None:
  502.             i = host.rfind(':')
  503.             j = host.rfind(']')
  504.             if i > j:
  505.                 
  506.                 try:
  507.                     port = int(host[i + 1:])
  508.                 except ValueError:
  509.                     raise InvalidURL("nonnumeric port: '%s'" % host[i + 1:])
  510.  
  511.                 host = host[:i]
  512.             else:
  513.                 port = self.default_port
  514.             if host and host[0] == '[' and host[-1] == ']':
  515.                 host = host[1:-1]
  516.             
  517.         
  518.         self.host = host
  519.         self.port = port
  520.  
  521.     
  522.     def set_debuglevel(self, level):
  523.         self.debuglevel = level
  524.  
  525.     
  526.     def connect(self):
  527.         msg = 'getaddrinfo returns an empty list'
  528.         for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM):
  529.             (af, socktype, proto, canonname, sa) = res
  530.             
  531.             try:
  532.                 self.sock = socket.socket(af, socktype, proto)
  533.                 if self.debuglevel > 0:
  534.                     print 'connect: (%s, %s)' % (self.host, self.port)
  535.                 
  536.                 self.sock.connect(sa)
  537.             except socket.error:
  538.                 msg = None
  539.                 if self.debuglevel > 0:
  540.                     print 'connect fail:', (self.host, self.port)
  541.                 
  542.                 if self.sock:
  543.                     self.sock.close()
  544.                 
  545.                 self.sock = None
  546.                 continue
  547.  
  548.         
  549.         if not self.sock:
  550.             raise socket.error, msg
  551.         
  552.  
  553.     
  554.     def close(self):
  555.         if self.sock:
  556.             self.sock.close()
  557.             self.sock = None
  558.         
  559.         if self._HTTPConnection__response:
  560.             self._HTTPConnection__response.close()
  561.             self._HTTPConnection__response = None
  562.         
  563.         self._HTTPConnection__state = _CS_IDLE
  564.  
  565.     
  566.     def send(self, str):
  567.         if self.sock is None:
  568.             if self.auto_open:
  569.                 self.connect()
  570.             else:
  571.                 raise NotConnected()
  572.         
  573.         if self.debuglevel > 0:
  574.             print 'send:', repr(str)
  575.         
  576.         
  577.         try:
  578.             self.sock.sendall(str)
  579.         except socket.error:
  580.             v = None
  581.             if v[0] == 32:
  582.                 self.close()
  583.             
  584.             raise 
  585.  
  586.  
  587.     
  588.     def _output(self, s):
  589.         self._buffer.append(s)
  590.  
  591.     
  592.     def _send_output(self):
  593.         self._buffer.extend(('', ''))
  594.         msg = '\r\n'.join(self._buffer)
  595.         del self._buffer[:]
  596.         self.send(msg)
  597.  
  598.     
  599.     def putrequest(self, method, url, skip_host = 0, skip_accept_encoding = 0):
  600.         if self._HTTPConnection__response and self._HTTPConnection__response.isclosed():
  601.             self._HTTPConnection__response = None
  602.         
  603.         if self._HTTPConnection__state == _CS_IDLE:
  604.             self._HTTPConnection__state = _CS_REQ_STARTED
  605.         else:
  606.             raise CannotSendRequest()
  607.         self._method = method
  608.         if not url:
  609.             url = '/'
  610.         
  611.         str = '%s %s %s' % (method, url, self._http_vsn_str)
  612.         self._output(str)
  613.         if self._http_vsn == 11:
  614.             if not skip_host:
  615.                 netloc = ''
  616.                 if url.startswith('http'):
  617.                     (nil, netloc, nil, nil, nil) = urlsplit(url)
  618.                 
  619.                 if netloc:
  620.                     
  621.                     try:
  622.                         netloc_enc = netloc.encode('ascii')
  623.                     except UnicodeEncodeError:
  624.                         netloc_enc = netloc.encode('idna')
  625.  
  626.                     self.putheader('Host', netloc_enc)
  627.                 else:
  628.                     
  629.                     try:
  630.                         host_enc = self.host.encode('ascii')
  631.                     except UnicodeEncodeError:
  632.                         host_enc = self.host.encode('idna')
  633.  
  634.                     if self.port == HTTP_PORT:
  635.                         self.putheader('Host', host_enc)
  636.                     else:
  637.                         self.putheader('Host', '%s:%s' % (host_enc, self.port))
  638.             
  639.             if not skip_accept_encoding:
  640.                 self.putheader('Accept-Encoding', 'identity')
  641.             
  642.         
  643.  
  644.     
  645.     def putheader(self, header, value):
  646.         if self._HTTPConnection__state != _CS_REQ_STARTED:
  647.             raise CannotSendHeader()
  648.         
  649.         str = '%s: %s' % (header, value)
  650.         self._output(str)
  651.  
  652.     
  653.     def endheaders(self):
  654.         if self._HTTPConnection__state == _CS_REQ_STARTED:
  655.             self._HTTPConnection__state = _CS_REQ_SENT
  656.         else:
  657.             raise CannotSendHeader()
  658.         self._send_output()
  659.  
  660.     
  661.     def request(self, method, url, body = None, headers = { }):
  662.         
  663.         try:
  664.             self._send_request(method, url, body, headers)
  665.         except socket.error:
  666.             v = None
  667.             if v[0] != 32 or not (self.auto_open):
  668.                 raise 
  669.             
  670.             self._send_request(method, url, body, headers)
  671.  
  672.  
  673.     
  674.     def _send_request(self, method, url, body, headers):
  675.         header_names = []([ k.lower() for k in headers ])
  676.         skips = { }
  677.         if 'accept-encoding' in header_names:
  678.             skips['skip_accept_encoding'] = 1
  679.         
  680.         self.putrequest(method, url, **skips)
  681.         if body and 'content-length' not in header_names:
  682.             self.putheader('Content-Length', str(len(body)))
  683.         
  684.         for hdr, value in headers.iteritems():
  685.             self.putheader(hdr, value)
  686.         
  687.         self.endheaders()
  688.         if body:
  689.             self.send(body)
  690.         
  691.  
  692.     
  693.     def getresponse(self):
  694.         if self._HTTPConnection__response and self._HTTPConnection__response.isclosed():
  695.             self._HTTPConnection__response = None
  696.         
  697.         if self._HTTPConnection__state != _CS_REQ_SENT or self._HTTPConnection__response:
  698.             raise ResponseNotReady()
  699.         
  700.         if self.debuglevel > 0:
  701.             response = self.response_class(self.sock, self.debuglevel, strict = self.strict, method = self._method)
  702.         else:
  703.             response = self.response_class(self.sock, strict = self.strict, method = self._method)
  704.         response.begin()
  705.         self._HTTPConnection__state = _CS_IDLE
  706.         if response.will_close:
  707.             self.close()
  708.         else:
  709.             self._HTTPConnection__response = response
  710.         return response
  711.  
  712.  
  713.  
  714. class SharedSocket:
  715.     
  716.     def __init__(self, sock):
  717.         self.sock = sock
  718.         self._refcnt = 0
  719.  
  720.     
  721.     def incref(self):
  722.         self._refcnt += 1
  723.  
  724.     
  725.     def decref(self):
  726.         self._refcnt -= 1
  727.         if self._refcnt == 0:
  728.             self.sock.close()
  729.         
  730.  
  731.     
  732.     def __del__(self):
  733.         self.sock.close()
  734.  
  735.  
  736.  
  737. class SharedSocketClient:
  738.     
  739.     def __init__(self, shared):
  740.         self._closed = 0
  741.         self._shared = shared
  742.         self._shared.incref()
  743.         self._sock = shared.sock
  744.  
  745.     
  746.     def close(self):
  747.         if not self._closed:
  748.             self._shared.decref()
  749.             self._closed = 1
  750.             self._shared = None
  751.         
  752.  
  753.  
  754.  
  755. class SSLFile(SharedSocketClient):
  756.     BUFSIZE = 8192
  757.     
  758.     def __init__(self, sock, ssl, bufsize = None):
  759.         SharedSocketClient.__init__(self, sock)
  760.         self._ssl = ssl
  761.         self._buf = ''
  762.         if not bufsize:
  763.             pass
  764.         self._bufsize = self.__class__.BUFSIZE
  765.  
  766.     
  767.     def _read(self):
  768.         buf = ''
  769.         while True:
  770.             
  771.             try:
  772.                 buf = self._ssl.read(self._bufsize)
  773.             except socket.sslerror:
  774.                 err = None
  775.                 if err[0] == socket.SSL_ERROR_WANT_READ or err[0] == socket.SSL_ERROR_WANT_WRITE:
  776.                     continue
  777.                 
  778.                 if err[0] == socket.SSL_ERROR_ZERO_RETURN or err[0] == socket.SSL_ERROR_EOF:
  779.                     break
  780.                 
  781.                 raise 
  782.                 continue
  783.                 except socket.error:
  784.                     err = None
  785.                     if err[0] == errno.EINTR:
  786.                         continue
  787.                     
  788.                     if err[0] == errno.EBADF:
  789.                         break
  790.                     
  791.                     raise 
  792.                     continue
  793.                 else:
  794.                     break
  795.                 None<EXCEPTION MATCH>socket.error
  796.             return buf
  797.  
  798.  
  799.     
  800.     def read(self, size = None):
  801.         L = [
  802.             self._buf]
  803.         avail = len(self._buf)
  804.         while size is None or avail < size:
  805.             s = self._read()
  806.             if s == '':
  807.                 break
  808.             
  809.             L.append(s)
  810.             avail += len(s)
  811.         all = ''.join(L)
  812.         if size is None:
  813.             self._buf = ''
  814.             return all
  815.         else:
  816.             self._buf = all[size:]
  817.             return all[:size]
  818.  
  819.     
  820.     def readline(self):
  821.         L = [
  822.             self._buf]
  823.         self._buf = ''
  824.         while None:
  825.             i = L[-1].find('\n')
  826.             if i >= 0:
  827.                 break
  828.             
  829.             s = self._read()
  830.             if s == '':
  831.                 break
  832.             
  833.             continue
  834.             if i == -1:
  835.                 return ''.join(L)
  836.             else:
  837.                 all = ''.join(L)
  838.                 i = all.find('\n') + 1
  839.                 line = all[:i]
  840.                 self._buf = all[i:]
  841.                 return line
  842.  
  843.     
  844.     def readlines(self, sizehint = 0):
  845.         total = 0
  846.         list = []
  847.         while True:
  848.             line = self.readline()
  849.             if not line:
  850.                 break
  851.             
  852.             list.append(line)
  853.             total += len(line)
  854.             if sizehint and total >= sizehint:
  855.                 break
  856.                 continue
  857.         return list
  858.  
  859.     
  860.     def fileno(self):
  861.         return self._sock.fileno()
  862.  
  863.     
  864.     def __iter__(self):
  865.         return self
  866.  
  867.     
  868.     def next(self):
  869.         line = self.readline()
  870.         if not line:
  871.             raise StopIteration
  872.         
  873.         return line
  874.  
  875.  
  876.  
  877. class FakeSocket(SharedSocketClient):
  878.     
  879.     class _closedsocket:
  880.         
  881.         def __getattr__(self, name):
  882.             raise error(9, 'Bad file descriptor')
  883.  
  884.  
  885.     
  886.     def __init__(self, sock, ssl):
  887.         sock = SharedSocket(sock)
  888.         SharedSocketClient.__init__(self, sock)
  889.         self._ssl = ssl
  890.  
  891.     
  892.     def close(self):
  893.         SharedSocketClient.close(self)
  894.         self._sock = self.__class__._closedsocket()
  895.  
  896.     
  897.     def makefile(self, mode, bufsize = None):
  898.         if mode != 'r' and mode != 'rb':
  899.             raise UnimplementedFileMode()
  900.         
  901.         return SSLFile(self._shared, self._ssl, bufsize)
  902.  
  903.     
  904.     def send(self, stuff, flags = 0):
  905.         return self._ssl.write(stuff)
  906.  
  907.     sendall = send
  908.     
  909.     def recv(self, len = 1024, flags = 0):
  910.         return self._ssl.read(len)
  911.  
  912.     
  913.     def __getattr__(self, attr):
  914.         return getattr(self._sock, attr)
  915.  
  916.  
  917.  
  918. class HTTPSConnection(HTTPConnection):
  919.     default_port = HTTPS_PORT
  920.     
  921.     def __init__(self, host, port = None, key_file = None, cert_file = None, strict = None):
  922.         HTTPConnection.__init__(self, host, port, strict)
  923.         self.key_file = key_file
  924.         self.cert_file = cert_file
  925.  
  926.     
  927.     def connect(self):
  928.         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  929.         sock.connect((self.host, self.port))
  930.         ssl = socket.ssl(sock, self.key_file, self.cert_file)
  931.         self.sock = FakeSocket(sock, ssl)
  932.  
  933.  
  934.  
  935. class HTTP:
  936.     _http_vsn = 10
  937.     _http_vsn_str = 'HTTP/1.0'
  938.     debuglevel = 0
  939.     _connection_class = HTTPConnection
  940.     
  941.     def __init__(self, host = '', port = None, strict = None):
  942.         if port == 0:
  943.             port = None
  944.         
  945.         self._setup(self._connection_class(host, port, strict))
  946.  
  947.     
  948.     def _setup(self, conn):
  949.         self._conn = conn
  950.         self.send = conn.send
  951.         self.putrequest = conn.putrequest
  952.         self.endheaders = conn.endheaders
  953.         self.set_debuglevel = conn.set_debuglevel
  954.         conn._http_vsn = self._http_vsn
  955.         conn._http_vsn_str = self._http_vsn_str
  956.         self.file = None
  957.  
  958.     
  959.     def connect(self, host = None, port = None):
  960.         if host is not None:
  961.             self._conn._set_hostport(host, port)
  962.         
  963.         self._conn.connect()
  964.  
  965.     
  966.     def getfile(self):
  967.         return self.file
  968.  
  969.     
  970.     def putheader(self, header, *values):
  971.         self._conn.putheader(header, '\r\n\t'.join(values))
  972.  
  973.     
  974.     def getreply(self):
  975.         
  976.         try:
  977.             response = self._conn.getresponse()
  978.         except BadStatusLine:
  979.             e = None
  980.             self.file = self._conn.sock.makefile('rb', 0)
  981.             self.close()
  982.             self.headers = None
  983.             return (-1, e.line, None)
  984.  
  985.         self.headers = response.msg
  986.         self.file = response.fp
  987.         return (response.status, response.reason, response.msg)
  988.  
  989.     
  990.     def close(self):
  991.         self._conn.close()
  992.         self.file = None
  993.  
  994.  
  995. if hasattr(socket, 'ssl'):
  996.     
  997.     class HTTPS(HTTP):
  998.         _connection_class = HTTPSConnection
  999.         
  1000.         def __init__(self, host = '', port = None, key_file = None, cert_file = None, strict = None):
  1001.             if port == 0:
  1002.                 port = None
  1003.             
  1004.             self._setup(self._connection_class(host, port, key_file, cert_file, strict))
  1005.             self.key_file = key_file
  1006.             self.cert_file = cert_file
  1007.  
  1008.  
  1009.  
  1010.  
  1011. class HTTPException(Exception):
  1012.     pass
  1013.  
  1014.  
  1015. class NotConnected(HTTPException):
  1016.     pass
  1017.  
  1018.  
  1019. class InvalidURL(HTTPException):
  1020.     pass
  1021.  
  1022.  
  1023. class UnknownProtocol(HTTPException):
  1024.     
  1025.     def __init__(self, version):
  1026.         self.args = (version,)
  1027.         self.version = version
  1028.  
  1029.  
  1030.  
  1031. class UnknownTransferEncoding(HTTPException):
  1032.     pass
  1033.  
  1034.  
  1035. class UnimplementedFileMode(HTTPException):
  1036.     pass
  1037.  
  1038.  
  1039. class IncompleteRead(HTTPException):
  1040.     
  1041.     def __init__(self, partial):
  1042.         self.args = (partial,)
  1043.         self.partial = partial
  1044.  
  1045.  
  1046.  
  1047. class ImproperConnectionState(HTTPException):
  1048.     pass
  1049.  
  1050.  
  1051. class CannotSendRequest(ImproperConnectionState):
  1052.     pass
  1053.  
  1054.  
  1055. class CannotSendHeader(ImproperConnectionState):
  1056.     pass
  1057.  
  1058.  
  1059. class ResponseNotReady(ImproperConnectionState):
  1060.     pass
  1061.  
  1062.  
  1063. class BadStatusLine(HTTPException):
  1064.     
  1065.     def __init__(self, line):
  1066.         self.args = (line,)
  1067.         self.line = line
  1068.  
  1069.  
  1070. error = HTTPException
  1071.  
  1072. class LineAndFileWrapper:
  1073.     
  1074.     def __init__(self, line, file):
  1075.         self._line = line
  1076.         self._file = file
  1077.         self._line_consumed = 0
  1078.         self._line_offset = 0
  1079.         self._line_left = len(line)
  1080.  
  1081.     
  1082.     def __getattr__(self, attr):
  1083.         return getattr(self._file, attr)
  1084.  
  1085.     
  1086.     def _done(self):
  1087.         self._line_consumed = 1
  1088.         self.read = self._file.read
  1089.         self.readline = self._file.readline
  1090.         self.readlines = self._file.readlines
  1091.  
  1092.     
  1093.     def read(self, amt = None):
  1094.         if self._line_consumed:
  1095.             return self._file.read(amt)
  1096.         
  1097.         if amt is None or amt > self._line_left:
  1098.             s = self._line[self._line_offset:]
  1099.             self._done()
  1100.             if amt is None:
  1101.                 return s + self._file.read()
  1102.             else:
  1103.                 return s + self._file.read(amt - len(s))
  1104.         else:
  1105.             i = self._line_offset
  1106.             j = i + amt
  1107.             s = self._line[i:j]
  1108.             self._line_offset = j
  1109.             self._line_left -= amt
  1110.             if self._line_left == 0:
  1111.                 self._done()
  1112.             
  1113.             return s
  1114.  
  1115.     
  1116.     def readline(self):
  1117.         if self._line_consumed:
  1118.             return self._file.readline()
  1119.         
  1120.         s = self._line[self._line_offset:]
  1121.         self._done()
  1122.         return s
  1123.  
  1124.     
  1125.     def readlines(self, size = None):
  1126.         if self._line_consumed:
  1127.             return self._file.readlines(size)
  1128.         
  1129.         L = [
  1130.             self._line[self._line_offset:]]
  1131.         self._done()
  1132.         if size is None:
  1133.             return L + self._file.readlines()
  1134.         else:
  1135.             return L + self._file.readlines(size)
  1136.  
  1137.  
  1138.  
  1139. def test():
  1140.     import sys
  1141.     import getopt
  1142.     (opts, args) = getopt.getopt(sys.argv[1:], 'd')
  1143.     dl = 0
  1144.     for o, a in opts:
  1145.         if o == '-d':
  1146.             dl = dl + 1
  1147.             continue
  1148.     
  1149.     host = 'www.python.org'
  1150.     selector = '/'
  1151.     if args[0:]:
  1152.         host = args[0]
  1153.     
  1154.     if args[1:]:
  1155.         selector = args[1]
  1156.     
  1157.     h = HTTP()
  1158.     h.set_debuglevel(dl)
  1159.     h.connect(host)
  1160.     h.putrequest('GET', selector)
  1161.     h.endheaders()
  1162.     (status, reason, headers) = h.getreply()
  1163.     print 'status =', status
  1164.     print 'reason =', reason
  1165.     print 'read', len(h.getfile().read())
  1166.     print 
  1167.     if headers:
  1168.         for header in headers.headers:
  1169.             print header.strip()
  1170.         
  1171.     
  1172.     print 
  1173.     
  1174.     class HTTP11(HTTP):
  1175.         _http_vsn = 11
  1176.         _http_vsn_str = 'HTTP/1.1'
  1177.  
  1178.     h = HTTP11('www.python.org')
  1179.     h.putrequest('GET', 'http://www.python.org/~jeremy/')
  1180.     h.endheaders()
  1181.     h.getreply()
  1182.     h.close()
  1183.     if hasattr(socket, 'ssl'):
  1184.         for host, selector in (('sourceforge.net', '/projects/python'),):
  1185.             print 'https://%s%s' % (host, selector)
  1186.             hs = HTTPS()
  1187.             hs.set_debuglevel(dl)
  1188.             hs.connect(host)
  1189.             hs.putrequest('GET', selector)
  1190.             hs.endheaders()
  1191.             (status, reason, headers) = hs.getreply()
  1192.             print 'status =', status
  1193.             print 'reason =', reason
  1194.             print 'read', len(hs.getfile().read())
  1195.             print 
  1196.             if headers:
  1197.                 for header in headers.headers:
  1198.                     print header.strip()
  1199.                 
  1200.             
  1201.             print 
  1202.         
  1203.     
  1204.  
  1205. if __name__ == '__main__':
  1206.     test()
  1207.  
  1208.